/*-------------------------------------------------------------------------
 *
 * xlogstats.c
 *		WAL统计信息的函数
 *
 * Copyright (c) 2022, PostgreSQL Global Development Group
 *
 * IDENTIFICATION
 *		src/backend/access/transam/xlogstats.c
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include "access/xlogreader.h"
#include "access/xlogstats.h"

/*
 * 计算记录的大小，分为 !FPI 和 FPI 部分。
 */
void XLogRecGetLen(XLogReaderState *fc_record, uint32 *fc_rec_len,
			  uint32 *fc_fpi_len)
{
	int			fc_block_id;

	/*
	 * 计算记录中 FPI 数据的数量。
	 *
	 * XXX: 我们查看 xlogreader 的私有解码备份块以获取
	 * bimg_len 指示 FPI 数据的长度。
	 */
	*fc_fpi_len = 0;
	for (fc_block_id = 0; fc_block_id <= XLogRecMaxBlockId(fc_record); fc_block_id++)
	{
		if (!XLogRecHasBlockRef(fc_record, fc_block_id))
			continue;

		if (XLogRecHasBlockImage(fc_record, fc_block_id))
			*fc_fpi_len += XLogRecGetBlock(fc_record, fc_block_id)->bimg_len;
	}

	/*
	 * 将记录的长度计算为总长度减去所有块图像的长度。
	 */
	*fc_rec_len = XLogRecGetTotalLen(fc_record) - *fc_fpi_len;
}

/*
 * 存储给定记录的每个 rmgr 和每个记录的统计信息。
 */
void XLogRecStoreStats(XLogStats *fc_stats, XLogReaderState *fc_record)
{
	RmgrId		fc_rmid;
	uint8		fc_recid;
	uint32		fc_rec_len;
	uint32		fc_fpi_len;

	Assert(fc_stats != NULL && fc_record != NULL);

	fc_stats->count++;

	fc_rmid = XLogRecGetRmid(fc_record);

	XLogRecGetLen(fc_record, &fc_rec_len, &fc_fpi_len);

	/* 更新每个 rmgr 的统计信息 */

	fc_stats->rmgr_stats[fc_rmid].count++;
	fc_stats->rmgr_stats[fc_rmid].rec_len += fc_rec_len;
	fc_stats->rmgr_stats[fc_rmid].fpi_len += fc_fpi_len;

	/*
	 * 更新每个记录的统计信息，其中记录通过 RmgrId 和 xl_info 字段中
	 * 的四个位组合来识别，这些位是 rmgr 的域（导致每个 RmgrId 有十六个可能的条目）。
	 */

	fc_recid = XLogRecGetInfo(fc_record) >> 4;

	/*
	 * XACT 记录需要不同的处理。这些记录使用四个位中的第一位作为
	 * 可选标志变量，后面的三位作为操作码。我们从 xl_info 中过滤出
	 * 操作码，并将其用作记录的标识符。
	 */
	if (fc_rmid == RM_XACT_ID)
		fc_recid &= 0x07;

	fc_stats->record_stats[fc_rmid][fc_recid].count++;
	fc_stats->record_stats[fc_rmid][fc_recid].rec_len += fc_rec_len;
	fc_stats->record_stats[fc_rmid][fc_recid].fpi_len += fc_fpi_len;
}
